package orm.spring;

import com.alibaba.fastjson.JSONObject;
import com.bjl.entity.User;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import orm.base.BaseController;
import orm.service.RedisService;
import orm.utils.HttpUtils;
import orm.utils.SerializeUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * 请求AOP拦截
 * Created by Ashin on 2017/9/28.
 */
@Component
@Aspect
public class DispatcherServletAop extends BaseController implements Ordered {

    private String[] withOutController = {"doLogin","doLoginBackend","login_page","doRegister","doQueryNormalChartRooms","doGetUnLoginUser","upload","doTest"};

    @Autowired
    RedisService redisService;

    @Pointcut("execution(* *.*.controller.*.*(..)) || execution(* *.controller.*.*(..)) || target(orm.base.Ex.BaseControllerEx)")
    public void doInit() {
    }


    @Around("doInit()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        //獲得Request對象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        //訪問完整目標方法路径
        String fullTargetPath = getFullTargetPath(joinPoint);
        //获得方法名
        String targetCls = joinPoint.getSignature().getName();
        Object o;
        // 过滤初始化seq res
        if (!targetCls.equals("setReqAndRes")) {
			if (!isHave(withOutController, targetCls)) {
                String token = request.getParameter("token");
				if (token == null) {
//                    User user = (User) request.getSession().getAttribute("user");
//                    if(user == null) {
//                        HttpUtils.outJson(this.codeMess(login_eCode, "登录超时！").toJSONString());
                    HttpUtils.call(request,response,this.codeMess(login_eCode, "登录超时！").toJSONString());

//                        return "redirect:/user/login_page";
                        return null;
//                    }
				}else{
				    try {
                        byte[] userByte = redisService.get(token.getBytes());
                        if (userByte == null) {
//                            HttpUtils.outJson(this.codeMess(login_eCode, "用户token失效，请重新登录！").toJSONString());
                            HttpUtils.call(request,response,this.codeMess(login_eCode, "用户token失效，请重新登录！").toJSONString());
                            return null;
                        }
                        long timeRemaining = redisService.timeRemaining(token.getBytes());
                        //更新redis时间
                        if (timeRemaining == -10 || timeRemaining < 900) {
                            redisService.set(token.getBytes(), userByte, RedisService.TWO_HOURS);
                        }
                        User user = (User) SerializeUtil.unserialize(userByte);
                        request.getSession().setAttribute("user", user);
                    }catch (Exception e){
				        logger.warn("redis连接超时",e);

                    }
                }
			}
            //log
            long sTime = new Date().getTime();
            //这里是执行的程序
            o = joinPoint.proceed();
            logger.info("正在請求 " + fullTargetPath + " 接口[請求耗時:" + (new Date().getTime() - sTime) + "ms]\n");
        } else {
            o = joinPoint.proceed();
        }
        if (o instanceof JSONObject) {
            HttpUtils.call(request,response,o.toString());
//            HttpUtils.outJson(o.toString());
            return null;
        } else {
            return o;
        }
    }

    /**
     * 优先级为最后
     *
     * @return
     */
    @Override
    public int getOrder() {
        return 999;
    }

    /**
     * 判断数组是否包含某个字符串
     *
     * @param strs
     * @param s
     * @return
     */
    public static boolean isHave(String[] strs, String s) {
        /*
         * 此方法有两个参数，第一个是要查找的字符串数组，第二个是要查找的字符或字符串
		 */
        for (int i = 0; i < strs.length; i++) {
            if (strs[i].equals(s)) {// 循环查找字符串数组中的每个字符串中是否包含所有查找的内容
                return true;// 查找到了就返回真，不在继续查询
            }
        }
        return false;// 没找到返回false
    }

    /**
     * 获得完整的目标路径
     *
     * @param joinPoint 切点
     * @return
     */
    public static String getFullTargetPath(ProceedingJoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        return targetMethod.getDeclaringClass().getName() + "." + targetMethod.getName();
    }
}
